<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>理解对象</title>
</head>

<body>
  <script>
    //Object.defineProperty()
    let person = {};
    Object.defineProperty(person, "name", {
      writable: false,
      value: "Nicholas"
    })
    person.name = "hhh";
    console.log(person.name);//Nicholas;属性的值不可修改
    //访问器属性
    let book = {
      year_: 2017,
      edition: 1
    }
    // 自定义访问器属性,设置get和set
    Object.defineProperty(book, "year", {
      get() {
        return this.year_;
      },
      set(newVal) {
        this.year_ = newVal;
        this.edition += newVal - 2017;
      }
    })
    book.year = 2022;
    console.log(book.edition);//6

    //一次性定义多个属性
    let book2 = {};
    Object.defineProperties(book2, {
      year_: {
        value: 2017
      },
      edition: {
        value: 1
      },
      year: {
        get() {
          return this.year_;
        },
        set(newVal) {
          if (newVal > 2017) {
            this.year_ = newVal;
            this.edition += newVal - 2017;
          }
        }
      }
    })
    //读取属性
    let descriptor = Object.getOwnPropertyDescriptor(book2, "year_");
    console.log(descriptor.value);
    let descriptor2 = Object.getOwnPropertyDescriptor(book2, "year");
    console.log(descriptor2);
    //Object.getOwnPropertyDescriptors()对每个属性都调用Object.getOwnPropertyDescriptor();
    let descriptor3 = Object.getOwnPropertyDescriptors(book2);
    console.log(descriptor3);
    //Object.assign()
    let dest = {};
    src1 = { id: 1 };
    src2 = { name: "Sloan" };
    let res = Object.assign(dest, src1, src2);
    console.log(res);//{id: 1, name: 'Sloan'}
    dest = {
      set a(val) {
        console.log(`Invoked dest setter with param ${val}`);
      }
    };
    src = {
      get a() {
        console.log("Invoked src getter");
        return "foo";
      }
    };
    Object.assign(dest, src1);
    //object.is()
    console.log(Object.is(NaN, NaN));//true
    //检查超过两个值,递归利用相等进行传递即可.
    function check(x, ...rest) {
      return Object.is(x, rest[0]) &&
        (rest.length < 2 || check(...rest));
    }
    console.log(check(2, 2, 2, 8));//检查多个值是否相等.
    //简写属性名:属性名与变量名相等时可以使用简写属性名.
    function makePerson(name) {
      return {
        name
      };
    }
    let p = makePerson("Sloan Li");
    console.log(p.name); //Sloan Li
    //可计算属性
    const nameKey = "name";
    const ageKey = "age";
    const jobKey = "job";
    let uniqueToken = 0;

    function getUniqueKey(key) {
      return `${key}_${uniqueToken++}`;
    }

    let person1 = {
      [getUniqueKey(nameKey)]: "Sloan",
      [getUniqueKey(ageKey)]: 22,
      [getUniqueKey(jobKey)]: "Software engineer"
    }
    console.log(person1);//{name_0: 'Sloan', age_1: 22, job_2: 'Software engineer'}
    //简写方法名
    let person3 = {
      sayName(name) {
        console.log(`My name is ${name}`);
      }
    }
    console.log(person3.sayName("li"));
    //解构赋值
    let p1 = {
      name: "Sloan",
      age: 22,
      job: {
        title: "Software engineer"
      }
    };
    //job使用了嵌套解构,外层属性没有定义会报错.
    let { name, age, job: { title } } = p1;
    console.log(name, age, title);
    let { length } = "abcdefg";
    console.log(length);//7
    //参数列表使用解构赋值
    let p3 = {
      name: "xxx",
      age: 22
    }
    function printPerson(foo, { name, age }, bar) {
      console.log(arguments);
      console.log(name, age);
    }
    printPerson("1st", p3, "2nd");
  </script>
</body>

</html>